;; The first four lines of this file were added by Dracula.
;; They tell DrScheme that this is a Dracula Modular ACL2 program.
;; Leave these lines unchanged so that DrScheme can properly load this file.
#reader(planet "reader.rkt" ("cce" "dracula.plt") "modular" "lang")
(require "itrim.lisp")

(require "iimage.lisp")
(require "icrop.lisp")
(require "icommon.lisp")


(module MTrim
  (include-book "list-utilities" :dir :teachpacks)
  (include-book "avl-rational-keys" :dir :teachpacks)
  (import IImage)
  (import ICrop)
  (import ICommon)
  
    (defun check-row (row pixel width i result)
    (if (> i width)
        result
        (if (not (equal pixel (cdr (avl-retrieve row i))))
            ;this pixel does not match, record
            (if (null (car result))
                ; result is empty, populate both field with this result
                (check-row row pixel width (+ i 1) (list i i))
                ; otherwise just update the second field
                (check-row row pixel width (+ i 1) (list (car result) i)))
            ;pixel does match, just move on
            (check-row row pixel width (+ i 1) result))))

    
    
  ; return the a list made up of the x values of the first and last non matching pixel
 ; ex (nil nil nil nil 3 7 2 5 nil nil) (trim two from top, 2 from left, i from bottom and width-5 right 
  
  (defun check-rows (tree pixel i)
    (if (> i (getHeight tree))
        nil
        (append (check-row (cdr (avl-retrieve tree i)) pixel (getWidth tree) 1 (list nil nil)) (check-rows tree pixel (+ i 1)))))
    
  (defun getpoints (xs i x1 y1 x2 y2 ycheck)
    (if (null xs)
        ;end of list, return
        (list x1 y1 x2 y2)
        ;check next two elements
    (let* ((p1 (car xs))
           (p2 (cadr xs))
           (tail (cddr xs)))
      (if (and (null p1) (null p1))
          ;if both are null, need to modify y
          (if (null ycheck)
              ;shave of top
              (getpoints tail (+ i 1) x1 (+ i 1) x2 y2 nil)
              ;shave of bottom
              (getpoints tail (+ i 1) x1 y1 x2 y2 't))
          ; if not both null
          (let* ((x1 (min x1 p1))
                 (x2 (max x2 p2)))
            (getpoints tail (+ i 1) x1 y1 x2 i 't))))))
      
  
  
  (defun trim-int (tree pixel) 
    (mv (car (MainCrop tree (getpoints (check-rows tree pixel 1) 1 (getWidth tree) 1 1 (getHeight tree) nil))) (list "Successfully trimmed image.")))
  
  (defun MainTrim (tree args)
    (cond
      ((null tree)                                           (mv tree (list "Error: empty image specified")))
      ((not (or (equal (len args) 0) (equal (len args) 3)))  (mv tree (list "Wrong number of arguments, expected either 0 or 3 arguments")))
      ((and (equal (len args) 3) (not (validPixel args)))  (mv tree (list "Argument does not specify a valid pixel, enter three numbers between 0 and 255")))
      (t                                                     (trim-int tree (if (null args) (getPixel tree 1 1) args)))))
  
    (export ITrim))